/**
 * ===========================================
 * 
 * 数据库类封装
 * 		1. 数据库多次连接，消耗资源问题。
 * 		2. 利用单例, 解决实例不共享问题。
 * 
 * ===========================================
 */

const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;
const dbConfig = require('./config.js');


class DB {
	
	/**
	 * 静态方法，实现单例
	 */
	static getInstance() {
		if(!DB.instance) {
			DB.instance = new DB();
		}
		return DB.instance;
	}
	
	/**
	 * 构造函数
	 */
	constructor () {
		this.dbClient = '';
		this.connect();  // 实例化时链接数据库
	}
	
	/**
	 * 连接数据库
	 */
	connect () {
		return new Promise((resolve, reject) => {
			if (this.dbClient) {
				resolve(this.dbClient);
				return;
			}
			
			MongoClient.connect(dbConfig.DBUrl, (err, client) => {
				if(err) {
					reject(err);
					return;
				}
				this.dbClient = client.db(dbConfig.dbName);
				resolve(this.dbClient);
			});
		});
	}
	
	/**
	 * id字符串转换成DB数据库使用的ObjectID
	 */
	getObjectID(id){
		return new ObjectID(id);
	}
	
	/**
	 * 查询
	 */
	findOne (collectionName, json) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				let result = db.collection(collectionName).find(json);
				result.toArray((err, docs) => {
					if(err){
						reject(err);
						return;
					}
					resolve(docs);
				});
			});
		});
	}
	
	/**
	 * 增加
	 */
	insertOne (collectionName, json) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				db.collection(collectionName).insetOne(json, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
	
	/**
	 * 修改
	 */
	updateOne (collectionName, json1, json2) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				
				db.collection(collectionName).updateOne(json1, {
					$set: json2
				}, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
	
	/**
	 * 删除
	 */
	deleteOne (collectionName, json) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				db.collection(collectionName).deleteOne(json, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
}


module.exports = DB.getInstance();